package lk.icta.core.dao.impl;

import lk.icta.common.dao.impl.BaseDAO;
import lk.icta.core.dao.PaymentDAO;
import lk.icta.core.entity.AlienationRailway;
import lk.icta.core.entity.Payment;
import lk.icta.user.entity.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * @author Supun Viraj Rathnayaka
 */

public class PaymentDAOImpl extends BaseDAO implements PaymentDAO {

    @Transactional(propagation = Propagation.MANDATORY)
    public void addPayment(Payment payment, User user) {

        logger.debug("Adding a payment {} by {}", payment.getReceiptReferenceNo(), user.getUsername());

        payment.getLifeCycleInfo().setCreatedUser(user);
        payment.getLifeCycleInfo().setCreatedTimeStamp(new Date());
        payment.getLifeCycleInfo().setLastUpdatedUser(user);
        payment.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());


        em.persist(payment);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void confirmPayment(Payment payment, User user) {

        payment.setConfirmedUser(user);
        payment.setConfirmedTimeStamp(new Date());
        payment.setPaymentState(Payment.PaymentState.CONFIRMED);

        payment.getLifeCycleInfo().setLastUpdatedUser(user);
        payment.getLifeCycleInfo().setLastUpdatedTimeStamp(new Date());
        em.merge(payment);
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public Payment getPaymentById(long paymentId, User user) {
        return em.find(Payment.class, paymentId);
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<Payment> getPaymentByUserAndState(Payment.PaymentState state, User user) {
        logger.debug("getPayment By User And State [User: {}] and State {}", user.getUsername(), state);
        Query q = em.createNamedQuery("getPaymentByUserAndState");
        q.setParameter("state", state);
        return q.getResultList();
    }

    @Transactional(propagation = Propagation.NEVER, readOnly = true)
    public List<Payment> getAllPaymentByUserAndState(Payment.PaymentState state, User user) {
        logger.debug("getAllPayment By User And State [User: {}] and State {}", user.getUsername(), state);
        Query q = em.createNamedQuery("getAllPaymentByUserAndState");
        q.setParameter("state", state);
        return q.getResultList();
    }

    @Override
    public List getPaymentsInTimeFrame(Map<String, Date> timeFrame, HashSet<AlienationRailway> alienationId) {
        Query q = em.createNamedQuery("getSumOfAllPaymentsInAlienationSetInTimeFrame");
        q.setParameter("startDate", timeFrame.get("startDate"));
        q.setParameter("endDate", timeFrame.get("endDate"));
        q.setParameter("alienationIdSet", alienationId);
        return q.getResultList();
    }

    private void populateDivisionList(Query q, User user) {

        if (user != null && user.getBranch() != null) {

            if(user.getDistricts() != null && user.getDistricts().size() > 0){
                logger.debug("role : {}", user.getRole().getName());
                q.setParameter("ignoreDS", 0);
                q.setParameter("DSList",user.getDistricts() );
                q.setParameter("branchId", user.getBranch().getId());
            }else{
                logger.debug("role  : {}", user.getRole().getName());
                q.setParameter("ignoreDS", 2);
                q.setParameter("DSList", null);
                q.setParameter("branchId", user.getBranch().getId());
            }



        } else {
            logger.debug("role  : {}", user.getRole().getName());
            q.setParameter("ignoreDS", 1);
            q.setParameter("DSList", null);
            q.setParameter("branchId", null);
        }

    }
}
